#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
总水表抄数模块
用于管理总水表抄数的记录、查询和统计功能
"""

import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from datetime import datetime

class TotalWaterMeterManager:
    """
    总水表抄数管理器类
    负责处理总水表抄数的添加、查询和展示功能
    """
    
    def __init__(self, root=None):
        """
        初始化总水表抄数管理器
        
        Args:
            root: 父窗口组件，默认为None
        """
        self.root = root
        self.db_path = 'water_electricity.db'
        self.initialize_database()
    
    def initialize_database(self):
        """
        初始化数据库，创建总水表抄数表（如果不存在）
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 创建总水表抄数表
            cursor.execute('''
            CREATE TABLE IF NOT EXISTS total_water_meter (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                month TEXT NOT NULL,
                reading REAL NOT NULL,
                water_usage REAL DEFAULT 0.0,  -- 本月用水量，存储窗口中计算的差额值
                record_date TEXT NOT NULL,
                UNIQUE(month)  -- 确保每个月只有一条记录
            )
            ''')
            
            # 如果表已存在但缺少water_usage字段，则添加该字段
            # 先检查表结构是否已包含water_usage字段
            cursor.execute("PRAGMA table_info(total_water_meter)")
            columns = [column[1] for column in cursor.fetchall()]
            if 'water_usage' not in columns:
                try:
                    cursor.execute("ALTER TABLE total_water_meter ADD COLUMN water_usage REAL DEFAULT 0.0")
                    print("已为total_water_meter表添加water_usage字段")
                except Exception as e:
                    print(f"添加water_usage字段时发生错误，但不影响程序运行: {str(e)}")
            
            conn.commit()
            conn.close()
        except Exception as e:
            print(f"初始化总水表数据库时发生错误: {str(e)}")
    
    def get_last_month_reading(self, current_month):
        """
        获取上个月的总水表读数
        
        Args:
            current_month: 当前月份，格式为'YYYY-MM'
            
        Returns:
            float: 上个月的总水表读数，如果没有记录或发生任何错误则返回0
        """
        try:
            # 解析当前月份
            if not current_month or '-' not in current_month:
                print(f"无效的月份格式: {current_month}")
                return 0.0
                
            year, month = map(int, current_month.split('-'))
            
            # 计算上个月
            month -= 1
            if month == 0:
                month = 12
                year -= 1
            
            last_month = f"{year:04d}-{month:02d}"
            
            # 查询上个月的读数
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            cursor.execute("SELECT reading FROM total_water_meter WHERE month = ?", (last_month,))
            result = cursor.fetchone()
            conn.close()
            
            # 确保即使result[0]为None或空值也返回0.0
            if result and result[0] is not None:
                try:
                    return float(result[0])
                except (ValueError, TypeError):
                    print(f"上月读数格式错误: {result[0]}")
                    return 0.0
            else:
                print(f"未找到上月 {last_month} 的水表读数记录")
                return 0.0
        except Exception as e:
            print(f"获取上月总水表读数时发生错误: {str(e)}")
            return 0.0
    
    def save_total_water_reading(self, month, reading, water_usage=0.0):
        """
        保存总水表读数和用水量
        
        Args:
            month: 月份，格式为'YYYY-MM'
            reading: 读数
            water_usage: 本月用水量（窗口中计算的差额值）
            
        Returns:
            bool: 保存是否成功
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 检查是否已存在该月记录
            cursor.execute("SELECT id FROM total_water_meter WHERE month = ?", (month,))
            existing = cursor.fetchone()
            
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            if existing:
                # 更新现有记录
                cursor.execute(
                    "UPDATE total_water_meter SET reading = ?, water_usage = ?, record_date = ? WHERE id = ?",
                    (reading, water_usage, current_time, existing[0])
                )
            else:
                # 插入新记录
                cursor.execute(
                    "INSERT INTO total_water_meter (month, reading, water_usage, record_date) VALUES (?, ?, ?, ?)",
                    (month, reading, water_usage, current_time)
                )
            
            conn.commit()
            conn.close()
            return True
        except Exception as e:
            print(f"保存总水表读数时发生错误: {str(e)}")
            return False
    
    def get_current_month_reading(self, month):
        """
        获取指定月份的总水表读数
        
        Args:
            month: 月份，格式为'YYYY-MM'
            
        Returns:
            float: 总水表读数，如果没有记录则返回0
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            cursor.execute("SELECT reading FROM total_water_meter WHERE month = ?", (month,))
            result = cursor.fetchone()
            conn.close()
            
            return float(result[0]) if result else 0.0
        except Exception as e:
            print(f"获取当月总水表读数时发生错误: {str(e)}")
            return 0.0
    
    def get_submeter_water_total(self, month):
        """
        获取指定月份所有分表的用水总量
        
        Args:
            month: 月份，格式为'YYYY-MM'
            
        Returns:
            float: 分表用水总量
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 计算指定月份所有分表的用水总量（本月读数减去上月读数）
            cursor.execute("""
            SELECT SUM(water_current - COALESCE(water_previous, 0)) 
            FROM meter_readings 
            WHERE strftime('%Y-%m', reading_date) = ?
            """, (month,))
            
            result = cursor.fetchone()
            conn.close()
            
            return float(result[0]) if result and result[0] is not None else 0.0
        except Exception as e:
            print(f"获取分表总读数时发生错误: {str(e)}")
            return 0.0
    
    def get_total_adjustment(self, month):
        """
        获取指定月份所有水表的调整量总和
        
        Args:
            month: 月份，格式为'YYYY-MM'
            
        Returns:
            float: 调整量总和
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 查询指定月份所有水表的调整量总和
            # 从meter_readings表中获取数据，使用water_adjustment字段
            cursor.execute("""
            SELECT SUM(water_adjustment) 
            FROM meter_readings 
            WHERE strftime('%Y-%m', reading_date) = ?
            """, (month,))
            
            result = cursor.fetchone()
            conn.close()
            
            return float(result[0]) if result and result[0] is not None else 0.0
        except Exception as e:
            print(f"获取调整量总和时发生错误: {str(e)}")
            return 0.0
    
    def get_all_readings(self, year=None, page=1, page_size=10):
        """
        获取所有总水表读数记录，支持年份筛选和分页，包含分表数据和差异计算
        
        Args:
            year: 筛选年份，格式为'YYYY'，为None时不筛选
            page: 页码，从1开始
            page_size: 每页记录数
            
        Returns:
            tuple: (total_count, records)
                total_count: 总记录数
                records: 当前页的记录列表，包含(month, reading, usage, submeter_total, total_adj, reading_diff, record_date, record_id)
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 计算偏移量
            offset = (page - 1) * page_size
            
            # 构建查询条件
            where_clause = "WHERE month LIKE ?" if year else ""
            params = [f"{year}-%"] if year else []
            
            # 获取总记录数
            count_sql = f"SELECT COUNT(*) FROM total_water_meter {where_clause}"
            cursor.execute(count_sql, params)
            total_count = cursor.fetchone()[0]
            
            # 获取分页数据（包含id字段用于编辑和删除，以及water_usage字段）
            data_sql = f"""
            SELECT id, month, reading, water_usage, record_date 
            FROM total_water_meter 
            {where_clause} 
            ORDER BY month DESC 
            LIMIT ? OFFSET ?
            """
            cursor.execute(data_sql, params + [page_size, offset])
            records = cursor.fetchall()
            
            # 处理每个记录的分表用水总量、调整读数和读数差异
            processed_records = []
            for record in records:
                # 现在记录包含id字段和water_usage字段
                record_id, month, reading, water_usage, record_date = record
                # 确保water_usage为有效数字且非负
                if not isinstance(water_usage, (int, float)) or water_usage < 0:
                    water_usage = 0.0
                
                # 获取分表用水总量
                submeter_water_total = self.get_submeter_water_total(month)
                # 确保分表用水总量为有效数字且非负
                if not isinstance(submeter_water_total, (int, float)) or submeter_water_total < 0:
                    submeter_water_total = 0.0
                
                # 获取调整量总和
                total_adjustment = self.get_total_adjustment(month)
                # 确保调整量为有效数字
                if not isinstance(total_adjustment, (int, float)):
                    total_adjustment = 0.0
                
                # 计算读数差异：本月用水量 - 分表用水总量 - 调整读数
                # 添加边界条件处理，确保所有变量都有有效数值
                reading_diff = water_usage - submeter_water_total - total_adjustment
                
                # 检查读数差异是否超过预设阈值（例如分表用水总量的10%）
                # 只有当分表用水总量不为0时才进行阈值检查
                threshold_percentage = 0.1  # 10%的阈值
                if submeter_water_total > 0 and abs(reading_diff) > (submeter_water_total * threshold_percentage):
                    # 记录差异日志，包含完整的计算参数，便于调试和分析
                    print(f"警告: 月份 {month} 的读数差异超出阈值。差异值: {reading_diff:.2f}, 阈值: {submeter_water_total * threshold_percentage:.2f}")
                    print(f"  计算参数: 本月用水量={water_usage:.2f}, 分表用水总量={submeter_water_total:.2f}, 调整读数={total_adjustment:.2f}")
                
                # 将所有数据添加到返回结果中
                processed_records.append((month, reading, water_usage, submeter_water_total, total_adjustment, reading_diff, record_date, record_id))
            
            conn.close()
            return total_count, processed_records
        except Exception as e:
            print(f"获取总水表记录时发生错误: {str(e)}")
            return 0, []
    
    def get_available_years(self):
        """
        获取数据库中存在的所有年份
        
        Returns:
            list: 年份列表，按降序排列
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 提取所有不同的年份
            cursor.execute("SELECT DISTINCT SUBSTR(month, 1, 4) as year FROM total_water_meter ORDER BY year DESC")
            years = [row[0] for row in cursor.fetchall()]
            
            conn.close()
            return years
        except Exception as e:
            print(f"获取可用年份时发生错误: {str(e)}")
            return []
    
    def update_total_water_reading(self, record_id, reading):
        """
        更新总水表读数记录
        
        Args:
            record_id: 记录ID
            reading: 新的读数
            
        Returns:
            bool: 更新是否成功
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            # 更新记录
            cursor.execute(
                "UPDATE total_water_meter SET reading = ?, record_date = ? WHERE id = ?",
                (reading, current_time, record_id)
            )
            
            success = cursor.rowcount > 0
            conn.commit()
            conn.close()
            return success
        except Exception as e:
            print(f"更新总水表读数时发生错误: {str(e)}")
            return False
    
    def delete_total_water_reading(self, record_id):
        """
        删除总水表读数记录
        
        Args:
            record_id: 记录ID
            
        Returns:
            bool: 删除是否成功
        """
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 删除记录
            cursor.execute("DELETE FROM total_water_meter WHERE id = ?", (record_id,))
            
            success = cursor.rowcount > 0
            conn.commit()
            conn.close()
            return success
        except Exception as e:
            print(f"删除总水表读数时发生错误: {str(e)}")
            return False

class TotalWaterMeterDialog:
    """
    总水表抄数对话框
    用于输入和显示总水表抄数信息，以及显示历史记录列表
    """
    
    def __init__(self, root, current_month):
        """
        初始化总水表抄数对话框
        
        Args:
            root: 父窗口组件
            current_month: 当前选中的月份
        """
        self.root = root
        self.current_month = current_month
        self.manager = TotalWaterMeterManager()
        self.dialog = None
        self.difference_var = None
        self.current_page = 1
        self.page_size = 10
        self.selected_year = tk.StringVar(value="全部")
        self.total_records = 0
        self.total_pages = 1
    
    def show_dialog(self):
        """
        显示总水表抄数对话框，包含左侧输入区域和右侧记录列表
        """
        # 创建对话框窗口
        self.dialog = tk.Toplevel(self.root)
        self.dialog.title("总水表抄数")
        self.dialog.geometry("900x500")  # 增大窗口尺寸以容纳左右布局
        self.dialog.resizable(True, True)
        self.dialog.transient(self.root)
        self.dialog.grab_set()
        
        # 计算居中位置
        self.dialog.update_idletasks()
        width = self.dialog.winfo_width()
        height = self.dialog.winfo_height()
        x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
        y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
        self.dialog.geometry(f"{width}x{height}+{x}+{y}")
        
        # 创建主框架
        main_frame = ttk.Frame(self.dialog, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建左右分栏
        left_frame = ttk.Frame(main_frame, width=400)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=10, pady=10)
        
        right_frame = ttk.Frame(main_frame)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 左侧输入区域
        self._setup_input_area(left_frame)
        
        # 右侧记录列表区域
        self._setup_records_area(right_frame)
    
    def _setup_input_area(self, parent):
        """
        设置左侧输入区域
        
        Args:
            parent: 父窗口组件
        """
        # 添加标题
        title_label = ttk.Label(parent, text="总水表抄数记录", font=("微软雅黑", 14, "bold"))
        title_label.pack(pady=(0, 20))
        
        # 月份显示
        month_frame = ttk.Frame(parent)
        month_frame.pack(fill=tk.X, pady=(0, 15))
        ttk.Label(month_frame, text="抄表月份:", font=("微软雅黑", 10)).pack(side=tk.LEFT, padx=(0, 10))
        month_value_label = ttk.Label(month_frame, text=self.current_month, font=("微软雅黑", 10, "bold"))
        month_value_label.pack(side=tk.LEFT)
        
        # 上月读数
        last_month_frame = ttk.Frame(parent)
        last_month_frame.pack(fill=tk.X, pady=(0, 15))
        ttk.Label(last_month_frame, text="上月总水表读数:", font=("微软雅黑", 10)).pack(side=tk.LEFT, padx=(0, 10))
        
        # 创建类属性用于存储上月读数和显示变量
        self.last_month_reading = 0.0
        self.last_reading_var = tk.StringVar(value="0.00")
        self.last_reading_entry = None
        
        # 获取上月读数
        try:
            reading = self.manager.get_last_month_reading(self.current_month)
            # 确保reading是有效的数字
            if reading is not None and isinstance(reading, (int, float)) and reading > 0:
                self.last_month_reading = float(reading)
                # 设置显示值，使用标签显示
                self.last_reading_var.set(f"{self.last_month_reading:.2f}")
                ttk.Label(last_month_frame, textvariable=self.last_reading_var, font=("微软雅黑", 10), foreground="blue").pack(side=tk.LEFT)
            else:
                # 上月读数为0或无效，显示可编辑的输入框
                print(f"上月读数为0或无效: {reading}，允许手动输入")
                self.last_month_reading = 0.0
                self.last_reading_var.set("")
                
                # 创建输入框并配置验证
                vcmd = (parent.register(self.validate_numeric_input), '%P')
                self.last_reading_entry = ttk.Entry(last_month_frame, textvariable=self.last_reading_var, 
                                                   width=15, font=("微软雅黑", 10), validate="key", validatecommand=vcmd)
                self.last_reading_entry.pack(side=tk.LEFT)
                
                # 添加提示标签
                ttk.Label(last_month_frame, text="(可编辑)", font=("微软雅黑", 8), foreground="gray").pack(side=tk.LEFT, padx=(5, 0))
                
                # 绑定输入事件，实时更新上月读数并重新计算差额
                self.last_reading_var.trace_add("write", lambda *args: self.on_last_reading_change())
        except Exception as e:
            print(f"显示上月读数时发生错误: {str(e)}")
            # 发生任何错误时，显示可编辑的输入框
            self.last_month_reading = 0.0
            self.last_reading_var.set("")
            
            vcmd = (parent.register(self.validate_numeric_input), '%P')
            self.last_reading_entry = ttk.Entry(last_month_frame, textvariable=self.last_reading_var, 
                                               width=15, font=("微软雅黑", 10), validate="key", validatecommand=vcmd)
            self.last_reading_entry.pack(side=tk.LEFT)
            
            ttk.Label(last_month_frame, text="(可编辑)", font=("微软雅黑", 8), foreground="gray").pack(side=tk.LEFT, padx=(5, 0))
            
            # 绑定输入事件
            self.last_reading_var.trace_add("write", lambda *args: self.on_last_reading_change())
        
        # 本月读数输入
        current_month_frame = ttk.Frame(parent)
        current_month_frame.pack(fill=tk.X, pady=(0, 20))
        ttk.Label(current_month_frame, text="本月总水表读数:", font=("微软雅黑", 10)).pack(side=tk.LEFT, padx=(0, 10))
        
        # 获取当月已有的读数（如果有）
        current_reading = self.manager.get_current_month_reading(self.current_month)
        self.current_reading_var = tk.StringVar(value=f"{current_reading:.2f}" if current_reading > 0 else "")
        current_reading_entry = ttk.Entry(current_month_frame, textvariable=self.current_reading_var, width=15, font=("微软雅黑", 10))
        current_reading_entry.pack(side=tk.LEFT)
        
        # 绑定输入事件，实时计算差额
        self.current_reading_var.trace_add("write", lambda *args: self.calculate_difference())
        
        # 差额显示
        difference_frame = ttk.Frame(parent)
        difference_frame.pack(fill=tk.X, pady=(0, 20))
        ttk.Label(difference_frame, text="本月用水量(差额):", font=("微软雅黑", 10)).pack(side=tk.LEFT, padx=(0, 10))
        
        self.difference_var = tk.StringVar(value="0.00")
        difference_label = ttk.Label(difference_frame, textvariable=self.difference_var, font=("微软雅黑", 10, "bold"), foreground="red")
        difference_label.pack(side=tk.LEFT)
        
        # 初始计算差额（如果有本月读数）
        if current_reading > 0:
            self.calculate_difference()
        
        # 按钮区域
        button_frame = ttk.Frame(parent)
        button_frame.pack(fill=tk.X, pady=(20, 0))
        
        # 保存按钮
        save_button = ttk.Button(button_frame, text="保存", command=lambda: self.save_reading(), width=15)
        save_button.pack(side=tk.LEFT, padx=(0, 10))
        
        # 取消按钮
        cancel_button = ttk.Button(button_frame, text="取消", command=self.dialog.destroy, width=15)
        cancel_button.pack(side=tk.LEFT)
    
    def _setup_records_area(self, parent):
        """
        设置右侧记录列表区域
        
        Args:
            parent: 父窗口组件
        """
        # 添加标题
        title_label = ttk.Label(parent, text="历史记录列表", font=("微软雅黑", 12, "bold"))
        title_label.pack(pady=(0, 10))
        
        # 筛选区域
        filter_frame = ttk.Frame(parent)
        filter_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(filter_frame, text="按年份筛选:", font=("微软雅黑", 10)).pack(side=tk.LEFT, padx=(0, 10))
        
        # 获取可用年份并设置下拉框
        years = self.manager.get_available_years()
        year_values = ["全部"] + years
        self.year_combobox = ttk.Combobox(filter_frame, textvariable=self.selected_year, values=year_values, state="readonly", width=10)
        self.year_combobox.current(0)
        self.year_combobox.pack(side=tk.LEFT, padx=(0, 10))
        
        # 筛选按钮
        filter_button = ttk.Button(filter_frame, text="筛选", command=self.filter_records)
        filter_button.pack(side=tk.LEFT)
        
        # 记录列表表格
        self.setup_table(parent)
        
        # 分页控件
        self.setup_pagination(parent)
        
        # 初始加载数据
        self.load_records()
    
    def setup_table(self, parent):
        """
        设置表格控件，包含右键菜单功能和新增的三列数据
        
        Args:
            parent: 父窗口组件
        """
        # 创建表格框架
        table_frame = ttk.Frame(parent)
        table_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        
        # 创建滚动条
        scrollbar_y = ttk.Scrollbar(table_frame, orient=tk.VERTICAL)
        scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)
        
        scrollbar_x = ttk.Scrollbar(table_frame, orient=tk.HORIZONTAL)
        scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 创建表格，添加新的三列：分表总读数、调整读数、读数差异
        self.tree = ttk.Treeview(table_frame, 
                               columns=("month", "reading", "usage", "submeter_total", "total_adj", "reading_diff", "record_date"), 
                               show="headings", yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
        
        # 设置列宽和标题
        self.tree.heading("month", text="月份")
        self.tree.heading("reading", text="本月抄表数")
        self.tree.heading("usage", text="本月用水量")
        self.tree.heading("submeter_total", text="分表用水总量")
        self.tree.heading("total_adj", text="调整读数")
        self.tree.heading("reading_diff", text="读数差异")
        self.tree.heading("record_date", text="记录时间")
        
        # 初始化列，不设置固定宽度，将通过auto_adjust_column_widths方法自动调整
        self.tree.column("month", anchor=tk.CENTER)
        self.tree.column("reading", anchor=tk.CENTER)
        self.tree.column("usage", anchor=tk.CENTER)
        self.tree.column("submeter_total", anchor=tk.CENTER)
        self.tree.column("total_adj", anchor=tk.CENTER)
        self.tree.column("reading_diff", anchor=tk.CENTER)
        self.tree.column("record_date", anchor=tk.CENTER)
        
        # 绑定滚动条
        scrollbar_y.config(command=self.tree.yview)
        scrollbar_x.config(command=self.tree.xview)
        
        # 创建右键菜单
        self._create_context_menu()
        
        # 绑定右键菜单事件
        self.tree.bind("<Button-3>", self._show_context_menu)
        
        # 允许表格随窗口大小调整而自动调整宽度
        self.tree.pack(fill=tk.BOTH, expand=True)
        
        # 绑定窗口大小变化事件，确保窗口大小变化时自动调整列宽
        if parent.master:
            parent.master.bind('<Configure>', self._on_window_resize)
        parent.bind('<Configure>', self._on_window_resize)
    
    def setup_pagination(self, parent):
        """
        设置分页控件
        
        Args:
            parent: 父窗口组件
        """
        pagination_frame = ttk.Frame(parent)
        pagination_frame.pack(fill=tk.X, pady=(10, 0))
        
        # 上一页按钮
        self.prev_button = ttk.Button(pagination_frame, text="上一页", command=self.prev_page)
        self.prev_button.pack(side=tk.LEFT, padx=(0, 10))
        
        # 页码显示
        self.page_info_var = tk.StringVar(value="第 1 页 / 共 1 页")
        page_info_label = ttk.Label(pagination_frame, textvariable=self.page_info_var)
        page_info_label.pack(side=tk.LEFT, padx=(0, 10))
        
        # 下一页按钮
        self.next_button = ttk.Button(pagination_frame, text="下一页", command=self.next_page)
        self.next_button.pack(side=tk.LEFT)
        
        # 记录总数显示
        self.total_info_var = tk.StringVar(value="共 0 条记录")
        total_info_label = ttk.Label(pagination_frame, textvariable=self.total_info_var)
        total_info_label.pack(side=tk.RIGHT)
    
    def load_records(self):
        """
        加载记录数据到表格，包含新增的三列数据
        """
        # 获取选中的年份
        year = self.selected_year.get()
        year = year if year != "全部" else None
        
        # 获取记录数据（包含新增的三列数据和id用于编辑和删除）
        self.total_records, records = self.manager.get_all_readings(year=year, page=self.current_page, page_size=self.page_size)
        
        # 计算总页数
        self.total_pages = (self.total_records + self.page_size - 1) // self.page_size
        
        # 更新页码信息
        self.page_info_var.set(f"第 {self.current_page} 页 / 共 {self.total_pages} 页")
        self.total_info_var.set(f"共 {self.total_records} 条记录")
        
        # 启用/禁用分页按钮
        self.prev_button.config(state=tk.DISABLED if self.current_page <= 1 else tk.NORMAL)
        self.next_button.config(state=tk.DISABLED if self.current_page >= self.total_pages else tk.NORMAL)
        
        # 清空表格
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 填充表格，包含新增的三列数据
        for record in records:
            # 现在记录包含更多字段：month, reading, usage, submeter_water_total, total_adj, reading_diff, record_date, record_id
            month, reading, usage, submeter_water_total, total_adj, reading_diff, record_date, record_id = record
            # 格式化显示所有数值数据
            formatted_reading = f"{reading:.2f}"
            formatted_usage = f"{usage:.2f}"
            formatted_submeter_water_total = f"{submeter_water_total:.2f}"
            formatted_total_adj = f"{total_adj:.2f}"
            formatted_reading_diff = f"{reading_diff:.2f}"
            # 插入表格行，将id作为行标识符，包含所有7列数据
            self.tree.insert("", tk.END, iid=record_id, 
                           values=(month, formatted_reading, formatted_usage, formatted_submeter_water_total, 
                                  formatted_total_adj, formatted_reading_diff, record_date))
        
        # 数据加载完成后自动调整列宽
        self.auto_adjust_column_widths()
    
    def filter_records(self):
        """
        根据筛选条件刷新记录列表
        """
        self.current_page = 1  # 重置到第一页
        self.load_records()
    
    def prev_page(self):
        """
        跳转到上一页
        """
        if self.current_page > 1:
            self.current_page -= 1
            self.load_records()
    
    def next_page(self):
        """
        跳转到下一页
        """
        if self.current_page < self.total_pages:
            self.current_page += 1
            self.load_records()
    
    def auto_adjust_column_widths(self):
        """
        自动调整表格列宽，基于列标题、单元格内容和表格容器尺寸
        智能计算列宽，尽量避免水平滚动条，同时确保内容完整显示
        确保在所有状态下（初始加载、筛选、页面切换、窗口大小变化）表现一致
        """
        # 确保表格已经初始化
        if not hasattr(self, 'tree') or not self.tree:
            return
        
        # 获取表格所有列
        columns = self.tree['columns']
        
        # 获取表格容器的可用宽度（更准确的计算方式）
        available_width = 0
        try:
            # 首先尝试获取表格自身的可用宽度
            if self.tree.winfo_ismapped():
                # 如果表格已经映射到屏幕，使用其实际宽度
                available_width = self.tree.winfo_width()
            else:
                # 否则尝试通过父容器计算
                if self.tree.master:
                    # 获取父容器的客户区宽度（减去内边距等）
                    available_width = self.tree.master.winfo_width()
                    # 减去表格的滚动条可能占用的空间
                    if hasattr(self, 'scrollbar_x') and self.scrollbar_x:
                        available_width -= self.scrollbar_x.winfo_width() or 20
            
            # 如果获取不到或宽度太小，使用一个合理的默认值
            if not available_width or available_width < 700:
                available_width = 700
        except Exception as e:
            print(f"获取可用宽度时出错: {str(e)}")
            # 出现异常时使用默认宽度
            available_width = 700
        
        # 为了避免水平滚动条，减去一些边距和边框
        available_width = available_width - 30  # 减去30像素作为表格边框和边距
        
        # 定义标准的最小宽度（确保一致性）
        standard_min_widths = {
            "record_date": 150,  # 日期时间列
            "month": 100,       # 月份列
            # 其他列的默认最小宽度
            "reading": 120,
            "usage": 120,
            "submeter_total": 130,
            "total_adj": 120,
            "reading_diff": 120
        }
        
        # 计算每列的理想宽度
        column_widths = {}
        column_min_widths = {}
        total_ideal_width = 0
        
        # 遍历每一列计算理想宽度
        for col in columns:
            # 获取列标题文本
            header_text = self.tree.heading(col, 'text')
            
            # 创建一个临时标签用于测量文本宽度
            temp_label = ttk.Label(self.tree, text=header_text)
            temp_label.grid(row=0, column=0, sticky='nsew')
            
            # 计算列标题的宽度
            header_width = temp_label.winfo_reqwidth() + 20  # 增加20像素作为边距
            temp_label.grid_forget()
            
            # 获取此列的标准最小宽度
            min_width = standard_min_widths.get(col, 120)
            # 确保最小宽度至少能容纳标题
            min_width = max(min_width, header_width)
            
            # 找出列中最长内容的宽度
            ideal_width = min_width
            
            # 遍历列中的所有单元格
            for item in self.tree.get_children():
                cell_value = self.tree.item(item, 'values')[columns.index(col)]
                
                # 创建临时标签测量单元格内容宽度
                temp_label = ttk.Label(self.tree, text=cell_value)
                temp_label.grid(row=0, column=0, sticky='nsew')
                
                # 计算单元格内容宽度
                cell_width = temp_label.winfo_reqwidth() + 20  # 增加20像素作为边距
                temp_label.grid_forget()
                
                # 更新理想宽度
                ideal_width = max(ideal_width, cell_width)
            
            column_min_widths[col] = min_width
            column_widths[col] = ideal_width
            total_ideal_width += ideal_width
        
        # 确保至少保留所有列的最小宽度
        total_min_width = sum(column_min_widths.values())
        
        # 定义一致的列宽调整策略
        # 1. 如果理想总宽度小于可用宽度，使用理想宽度并保持一致的比例
        if total_ideal_width <= available_width:
            # 直接使用各列的理想宽度
            for col in columns:
                self.tree.column(col, width=column_widths[col], stretch=False)
        # 2. 如果理想总宽度超过可用宽度，但最小宽度总和小于可用宽度，按比例分配
        elif total_min_width <= available_width:
            # 计算可用于按比例分配的额外宽度
            remaining_width = available_width - total_min_width
            
            # 计算每列相对于理想额外宽度的比例
            width_ratios = {}
            total_ratio = 0
            for col in columns:
                extra_width = column_widths[col] - column_min_widths[col]
                width_ratios[col] = extra_width
                total_ratio += extra_width
            
            # 按比例分配额外宽度
            for col in columns:
                if total_ratio > 0:
                    additional_width = int((width_ratios[col] / total_ratio) * remaining_width)
                else:
                    additional_width = 0
                
                final_width = column_min_widths[col] + additional_width
                self.tree.column(col, width=final_width, stretch=False)
        # 3. 如果最小宽度总和也超过可用宽度，按比例缩小所有列
        else:
            # 计算缩放比例
            scale_factor = available_width / total_min_width
            
            # 按比例缩小每列（确保至少有最小可读宽度）
            for col in columns:
                scaled_width = max(int(column_min_widths[col] * scale_factor), 80)  # 确保最小80像素
                self.tree.column(col, width=scaled_width, stretch=False)
    
    def _on_window_resize(self, event=None):
        """
        窗口大小变化事件处理函数
        当窗口大小改变时，重新调整表格列宽
        
        Args:
            event: 事件对象（可选）
        """
        # 添加一个小延迟，确保窗口已经完全调整大小
        if hasattr(self, 'tree') and self.tree:
            # 使用after方法延迟调整，以避免频繁调整
            self.tree.after(100, self.auto_adjust_column_widths)
    
    def calculate_difference(self):
        """
        计算本月与上月读数的差额（本月用水量）
        计算公式：本月用水量 = 本月抄表数 - 上月总水表读数
        确保结果为非负数值，并处理边界条件
        """
        try:
            # 获取本月抄表数
            current_reading_str = self.current_reading_var.get().strip()
            if current_reading_str:
                current_reading = float(current_reading_str)
                # 检查本月读数是否为有效正数
                if current_reading < 0:
                    self.difference_var.set("本月读数不能为负")
                    return
                
                # 确保上月读数为有效数字
                if not isinstance(self.last_month_reading, (int, float)):
                    self.difference_var.set("上月读数错误")
                    return
                
                # 计算本月用水量 = 本月抄表数 - 上月总水表读数
                difference = current_reading - self.last_month_reading
                
                # 确保结果为非负数值
                difference = max(0.0, difference)
                
                # 显示计算结果
                self.difference_var.set(f"{difference:.2f}")
            else:
                self.difference_var.set("0.00")
        except ValueError:
            self.difference_var.set("输入错误")
        except Exception as e:
            print(f"计算本月用水量时发生错误: {str(e)}")
            self.difference_var.set("计算错误")
    
    def validate_numeric_input(self, new_value):
        """
        验证输入是否为有效的数字
        
        Args:
            new_value: 输入框的新值
            
        Returns:
            bool: 如果输入有效则返回True，否则返回False
        """
        # 允许空输入
        if new_value == "":
            return True
            
        # 检查是否为有效的数字（整数或小数）
        try:
            value = float(new_value)
            # 确保输入是非负数
            if value < 0:
                return False
            return True
        except ValueError:
            return False
    
    def on_last_reading_change(self):
        """
        当月读数改变时的事件处理
        更新上月读数并重新计算差额
        """
        try:
            # 获取输入框的值
            input_value = self.last_reading_var.get()
            
            # 更新上月读数
            if input_value:
                self.last_month_reading = float(input_value)
            else:
                self.last_month_reading = 0.0
                
            # 重新计算差额
            self.calculate_difference()
        except Exception as e:
            print(f"处理上月读数输入时发生错误: {str(e)}")
            self.last_month_reading = 0.0
    
    def save_reading(self):
        """
        保存总水表读数并刷新记录列表
        """
        try:
            reading_str = self.current_reading_var.get().strip()
            if not reading_str:
                messagebox.showerror("错误", "请输入本月总水表读数！")
                return
            
            reading = float(reading_str)
            if reading < 0:
                messagebox.showerror("错误", "读数不能为负数！")
                return
            
            # 验证本月读数是否大于上月读数
            if reading < self.last_month_reading:
                messagebox.showerror("错误", "本月读数不能小于上月读数！")
                return
            
            # 验证手动输入的上月读数（如果有输入框）
            if self.last_reading_entry is not None:
                last_reading_input = self.last_reading_var.get()
                if last_reading_input:
                    # 验证手动输入的上月读数格式
                    try:
                        manual_last_reading = float(last_reading_input)
                        if manual_last_reading < 0:
                            messagebox.showerror("错误", "上月读数不能为负数！")
                            self.last_reading_entry.focus()
                            return
                    except ValueError:
                        messagebox.showerror("错误", "上月读数格式不正确！")
                        self.last_reading_entry.focus()
                        return
                    
                    # 如果手动输入了上月读数，更新内部值
                    self.last_month_reading = manual_last_reading
            
            # 获取窗口中计算的本月用水量差额值
            try:
                # 从difference_var获取差额值并转换为浮点数
                difference_str = self.difference_var.get()
                # 检查是否是有效的数字字符串（不是错误信息）
                if difference_str not in ["本月读数不能为负", "上月读数错误", "输入错误", "计算错误"]:
                    water_usage = float(difference_str)
                else:
                    # 如果差额值无效，设为0
                    water_usage = 0.0
            except (ValueError, TypeError):
                # 如果转换失败，设为0
                water_usage = 0.0
                print("无法获取有效差额值，使用默认值0")
            
            # 保存读数和用水量差额值
            if self.manager.save_total_water_reading(self.current_month, reading, water_usage):
                messagebox.showinfo("成功", "总水表读数保存成功！")
                # 刷新记录列表
                self.filter_records()
                # 更新年份下拉框
                self._update_year_combobox()
            else:
                messagebox.showerror("错误", "保存失败，请重试！")
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字！")
        except Exception as e:
            print(f"保存读数时发生错误: {str(e)}")
            messagebox.showerror("错误", f"保存过程中发生错误: {str(e)}")
    
    def _update_year_combobox(self):
        """
        更新年份下拉框选项
        """
        try:
            # 获取当前选中的值
            current_value = self.selected_year.get()
            
            # 获取最新的可用年份
            years = self.manager.get_available_years()
            year_values = ["全部"] + years
            
            # 更新下拉框
            self.year_combobox['values'] = year_values
            
            # 如果当前选中的值不存在于新的选项中，选择"全部"
            if current_value not in year_values:
                self.selected_year.set("全部")
        except Exception as e:
            print(f"更新年份下拉框时发生错误: {str(e)}")
    
    def _create_context_menu(self):
        """
        创建右键菜单
        """
        self.context_menu = tk.Menu(self.dialog, tearoff=0)
        self.context_menu.add_command(label="编辑记录", command=self._edit_record)
        self.context_menu.add_command(label="删除记录", command=self._delete_record)
    
    def _show_context_menu(self, event):
        """
        显示右键菜单
        
        Args:
            event: 鼠标事件
        """
        # 尝试选中鼠标点击的行
        item = self.tree.identify_row(event.y)
        if item:
            self.tree.selection_set(item)
            # 在鼠标位置显示菜单
            self.context_menu.post(event.x_root, event.y_root)
    
    def _edit_record(self):
        """
        编辑选中的记录
        """
        selected_items = self.tree.selection()
        if not selected_items:
            messagebox.showinfo("提示", "请先选择要编辑的记录")
            return
        
        # 获取选中的记录ID和数据
        record_id = selected_items[0]
        item_values = self.tree.item(record_id, "values")
        
        if not item_values:
            messagebox.showerror("错误", "无法获取记录数据")
            return
        
        month, current_reading_str = item_values[0], item_values[1]
        
        # 创建编辑对话框
        edit_dialog = tk.Toplevel(self.dialog)
        edit_dialog.title(f"编辑 {month} 记录")
        edit_dialog.geometry("400x200")
        edit_dialog.transient(self.dialog)
        edit_dialog.grab_set()
        
        # 计算居中位置
        edit_dialog.update_idletasks()
        width = edit_dialog.winfo_width()
        height = edit_dialog.winfo_height()
        x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
        y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
        edit_dialog.geometry(f"{width}x{height}+{x}+{y}")
        
        # 编辑框架
        frame = ttk.Frame(edit_dialog, padding=20)
        frame.pack(fill=tk.BOTH, expand=True)
        
        # 月份显示
        month_frame = ttk.Frame(frame)
        month_frame.pack(fill=tk.X, pady=(0, 15))
        ttk.Label(month_frame, text="月份:", font=("微软雅黑", 10)).pack(side=tk.LEFT, padx=(0, 10))
        ttk.Label(month_frame, text=month, font=("微软雅黑", 10, "bold")).pack(side=tk.LEFT)
        
        # 读数输入
        reading_frame = ttk.Frame(frame)
        reading_frame.pack(fill=tk.X, pady=(0, 20))
        ttk.Label(reading_frame, text="水表读数:", font=("微软雅黑", 10)).pack(side=tk.LEFT, padx=(0, 10))
        
        reading_var = tk.StringVar(value=current_reading_str)
        reading_entry = ttk.Entry(reading_frame, textvariable=reading_var, width=15, font=("微软雅黑", 10))
        reading_entry.pack(side=tk.LEFT)
        reading_entry.focus()
        
        # 按钮区域
        button_frame = ttk.Frame(frame)
        button_frame.pack(fill=tk.X, pady=(20, 0))
        
        def save_changes():
            try:
                reading_str = reading_var.get().strip()
                if not reading_str:
                    messagebox.showerror("错误", "请输入水表读数！")
                    return
                
                reading = float(reading_str)
                if reading < 0:
                    messagebox.showerror("错误", "读数不能为负数！")
                    return
                
                # 更新记录
                if self.manager.update_total_water_reading(record_id, reading):
                    messagebox.showinfo("成功", "记录更新成功！")
                    # 刷新记录列表
                    self.filter_records()
                    edit_dialog.destroy()
                else:
                    messagebox.showerror("错误", "更新失败，请重试！")
            except ValueError:
                messagebox.showerror("错误", "请输入有效的数字！")
            except Exception as e:
                print(f"保存编辑时发生错误: {str(e)}")
                messagebox.showerror("错误", f"保存过程中发生错误: {str(e)}")
        
        # 保存按钮
        save_button = ttk.Button(button_frame, text="保存", command=save_changes, width=15)
        save_button.pack(side=tk.LEFT, padx=(0, 10))
        
        # 取消按钮
        cancel_button = ttk.Button(button_frame, text="取消", command=edit_dialog.destroy, width=15)
        cancel_button.pack(side=tk.LEFT)
    
    def _delete_record(self):
        """
        删除选中的记录
        """
        selected_items = self.tree.selection()
        if not selected_items:
            messagebox.showinfo("提示", "请先选择要删除的记录")
            return
        
        # 获取选中的记录ID和数据
        record_id = selected_items[0]
        item_values = self.tree.item(record_id, "values")
        
        if not item_values:
            messagebox.showerror("错误", "无法获取记录数据")
            return
        
        month = item_values[0]
        
        # 确认删除
        if messagebox.askyesno("确认删除", f"确定要删除 {month} 的记录吗？"):
            try:
                # 删除记录
                if self.manager.delete_total_water_reading(record_id):
                    messagebox.showinfo("成功", "记录删除成功！")
                    # 刷新记录列表
                    self.filter_records()
                    # 更新年份下拉框
                    self._update_year_combobox()
                else:
                    messagebox.showerror("错误", "删除失败，请重试！")
            except Exception as e:
                print(f"删除记录时发生错误: {str(e)}")
                messagebox.showerror("错误", f"删除过程中发生错误: {str(e)}")

# 模块测试函数
def test_module():
    """
    测试总水表抄数模块的功能
    """
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口
    
    # 测试对话框
    dialog = TotalWaterMeterDialog(root, "2024-11")
    dialog.show_dialog()
    
    root.mainloop()

if __name__ == "__main__":
    test_module()
